package com.fbms.common.result;

import lombok.Getter;

import static com.fbms.common.result.ResFlag.*;


/**
 * 统一返回实体
 * 由于是返回实体，内容较多，所以提供了构建器，同时res一般是不会改变的，所以只提供了get方法。
 * 同时此实体只能通过构建器构建。
 *
 * @param <T> 数据的类型（data's type）
 * @author lan
 * @since 2023/03/15  10:33
 */
@Getter
public class Res<T> {


    /**
     * 构造方法（通过builder构建 ）
     *
     * @param builder 构建器
     */
    private Res(ResponseDataBeanBuilder<T> builder) {
        this.data = builder.data;
        this.msg = builder.msg;
        this.status = builder.status;
        this.flag = builder.flag;
        this.code = builder.code;
    }

    /**
     * 构造方法（通过builder构建 ）
     *
     * @param builder 构建器
     */
    protected Res(ResBuilder<T> builder) {
        this.data = builder.getData();
        this.msg = builder.getMsg();
        this.status = builder.getStatus();
        this.flag = builder.getFlag();
        this.code = builder.getCode();
    }


    /**
     * 返回前台数据
     */
    private final T data;


    /**
     * 返回前台成功失败标志
     */
    private final String flag;

    /**
     * 返回消息
     */
    private final String msg;


    /**
     * 返回状态码
     */
    private final Integer code;


    /**
     * 返回状态位
     */
    private final String status;


    /**
     * res的构建器
     *
     * @param <T> data的类型
     * @author immort-liuzyj(zyliu)
     */
    public static class ResponseDataBeanBuilder<T> {

        /**
         * 通过数据直接构造一个结果出来。
         *
         * @param t   数据
         * @param <T> 类型
         * @return 结果
         */
        public static <T> Res<T> of(T t) {
            return ResponseDataBeanBuilder.<T>successBuilder()
                    .data(t)
                    .build();
        }

        /**
         * 错误结果集的 快速干煸
         *
         * @param msg 消息
         * @param <T> 类型
         * @return 结果
         */
        public static <T> Res<T> ofError(String msg) {
            return ResponseDataBeanBuilder.<T>errorBuilder()
                    .msg(msg)
                    .build();
        }

        public static <T> ResponseDataBeanBuilder<T> successBuilder() {
            return new ResponseDataBeanBuilder<T>()
                    .flag(FLAG_SUCCESS)
                    .code(ResStatus.success.getCode())
                    .msg(ResStatus.success.getMsg());
        }

        public static <T> ResponseDataBeanBuilder<T> errorBuilder() {
            return new ResponseDataBeanBuilder<T>()
                    .flag(FLAG_FAIL)
                    .code(ResStatus.fail.getCode())
                    .msg(ResStatus.fail.getMsg());
        }

        public static <T> ResponseDataBeanBuilder<T> failBuilder() {
            return new ResponseDataBeanBuilder<T>()
                    .flag(FLAG_FAIL)
                    .code(ResStatus.fail.getCode())
                    .msg(ResStatus.fail.getMsg());
        }


        public static <T> ResponseDataBeanBuilder<T> warnBuilder() {
            return new ResponseDataBeanBuilder<T>()
                    .flag(FLAG_WARN)
                    .code(ResStatus.warn.getCode())
                    .msg(ResStatus.warn.getMsg());
        }



        /**
         * 构建出 ResponseDataBean，根据builder中的内容
         *
         * @return ResponseDataBean
         */
        public Res<T> build() {
            return new Res<>(this);
        }


        /**
         * 返回前台数据
         */
        private T data;


        /**
         * 返回前台成功失败标志
         */
        private String flag;

        /**
         * 返回消息
         */
        private String msg;

        /**
         * 返回状态码
         */
        private Integer code;


        /**
         * 返回状态位
         */
        private String status;

        public ResponseDataBeanBuilder<T> status(String status) {
            this.status = status;
            return this;
        }

        public ResponseDataBeanBuilder<T> code(Integer code) {
            this.code = code;
            return this;
        }

        public ResponseDataBeanBuilder<T> msg(String msg) {
            this.msg = msg;
            return this;
        }

        public ResponseDataBeanBuilder<T> flag(String flag) {
            this.flag = flag;
            return this;
        }

        public ResponseDataBeanBuilder<T> data(T data) {
            this.data = data;
            return this;
        }
    }
}
